package org.lab.tracecash.common.serialization;

import java.lang.reflect.Type;
import java.util.Date;

import javax.inject.Inject;
import javax.inject.Singleton;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.gson.ExclusionStrategy;
import com.google.gson.FieldAttributes;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.inject.Injector;

@Singleton
public class Serializer {

	private final static Logger LOG = LoggerFactory.getLogger(Serializer.class);

	private final Gson serializer;
	private final GsonBuilder gsonBuilder;
	private final ExclusionStrategy strategy = new ExclusionStrategy() {

		@Override
		public boolean shouldSkipField(FieldAttributes f) {
			return f.getAnnotation(NotSerializable.class) != null;
		}

		@Override
		public boolean shouldSkipClass(Class<?> clazz) {
			return clazz.getAnnotation(NotSerializable.class) != null;
		}
	};

	@Inject
	public Serializer(Injector injector) {
		LOG.info("Initializing serializer");
		gsonBuilder = new GsonBuilder();
		gsonBuilder.addSerializationExclusionStrategy(strategy);
		gsonBuilder.registerTypeHierarchyAdapter(Date.class, new DateSerializer("yyyy-MM-dd'T'HH:mm:ss.SSSZ", "dd/MM/yyyy", "ddMMyyyy"));
		// gsonBuilder.registerTypeAdapter(AbstractLegalEntity.class, injector.getInstance(AbstractLegalEntitySerializer.class));
		serializer = gsonBuilder.create();
	}

	public String toJson(Object src, Type typeOfSrc) {
		return serializer.toJson(src, typeOfSrc);
	}

	public String toJson(Object src) {
		return serializer.toJson(src);
	}

	public <T> T fromJson(String json, Class<T> classOfT) {
		return serializer.fromJson(json, classOfT);
	}

	public <T> T fromJson(String json, Type type) {
		return serializer.fromJson(json, type);
	}

	public Gson get() {
		return serializer;
	}

	public GsonBuilder getBuilder() {
		return gsonBuilder;
	}
}